6. Dictionaries (associative arrays)

  1. Another data type of collection of values - dictionary
    • Lists, tuples, and strings use integer indexes to access the values, called elements, stored in them. Let's try the next example.
      records = [89, 45, 23, 66, 3, -5]  # a list
      records[2] = 20
      print(records[2])
      records = (89, 45, 23, 66, 3, -5)  # a tuple
      print(records[2])
      name = 'Williams'
      print(name[5])
      
    • Dictionaries use {...}, and indexes in a dictionary are keys. Keys can be strings and integers. But usually string values. Obviously those keys should be all different in a dictionary so that a specific value can be accessed through its key. Let's try the next example.
      key5 = 'country'
      records = {'name': 'John', 'id': 345678, 'age':20, 10: 'Kamloops', key5: 'Canada'}  # {...}; key5 ???
      records['age'] = 19
      print(records['age'])
      print(records['address'])  # ???
      
    • Let's try the next example that reads values from the user and saves them into a dictionary.
      def readRecord():
          records = {}  # empty records
          records['name'] = input("Name: ")
          records['id'] = int(input("Id: "))
          records['age'] = int(input("Age: "))
          return records
      
      records = readRecord()
      print(records)
      
    • Once thing that dictionaries are different from lists is that they cannot be sliced like lists. This is because values are not listed with integer indexes.
    • Can we take out keys from a dictionary and put them into a list? How? Type conversion function. Try the next example.
      records = {'name': 'John', 'id': 345678, 'age':20}  # {...}
      keys = list(records)
      print(keys)
      for k in keys:
          print(k)
          print(records[k])
          print(k + "-> " + str(records[k]))
      
  2. Methods for dictionaries
    • How to get all the keys - .keys(). Let's try the next example.
      records = {'name': 'John', 'id': 345678, 'age':20}  # {...}
      keys = records.keys()
      print(keys)
      for k in records.keys():
          print(k + "-> " + str(records[k]))
      
    • How to get all the values - .values(). Let's try the next example.
      records = {'name': 'John', 'id': 345678, 'age':20}  # {...}
      values = records.values()
      print(values)
      for v in records.values():
          print(v)
      
    • How to get all the key-value pairs - .items(). Let's try the next example. The return values from items() are tuples, not lists nor dictionaries.
      records = {'name': 'John', 'id': 345678, 'age':20}  # {...}
      items = records.items()
      print(items)
      for it in records.items():
          print(it)
      
    • A method to get a value with a key - .get(). Let's try the next example. get(k, v) returns the value of the key k when the k exists. If the key k does not exist, v will be returned.
      records = {'name': 'John', 'id': 345678, 'age':20}  # {...}
      print(records['name'] + '\' lives in ' + records.get('country', 'Not defined'))
      records['country'] = input("Country: ")
      print(records['name'] + '\' lives in ' + records.get('country', 'Not defined'))
      
    • A method to set a default value - .setdefault(). Let's try the next example. setdefault(k, v) sets the value v of the key k only when the k does not exist. If the key k does not exist, v will be returned. Otherwise, the existing value will be returned.
      records = {'name': 'John', 'id': 345678, 'age':20}  # {...}
      print(records['name'] + '\' lives in ' + records.setdefault('country', 'Canada'))
      print(records['name'] + '\' lives in ' + records.setdefault('country', 'US'))  # ???
      print(records['country'])  # ???
      records['country'] = 'US'
      print(records['country'])  # ???
      
  3. Operators for dictionaries - in and not in
    • How to check if a key exists - in and not in. Let's try the next example.
      records = {'name': 'John', 'id': 345678, 'age':20}  # {...}
      
      if 'name' in records:
          print('Name: ' + records['name'])
      if 'country' not in records:
          records['country'] = input("Country: ")
          print(records)
      
      if 'country' in records.keys():
          print(records['country'])
      if 'Canada' not in records.values():
          print("Not Canada")
      
  4. Nested dictionaries and lists
    • Let's try the next example of a dictionary of lists.
      students = {'John': [20, 'CS', 'TRU'], 'Caren': [19, 'MATH', 'TRU'], 'Snape': [58, 'Potion', 'Hogwarts']}
      print(students['John'])
      
    • Let's try the next example of a list of dictionaries.
      students = [{'name':'John', 'age':20, 'major':'CS', 'school':'TRU'},
          {'name':'Caren', 'age':19, 'major':'MATH', 'school':'TRU'}, 
          {'name':'Snape', 'age':58, 'major':'Potion', 'school':'Hogwarts'}]
      print(students[0])
      
    • Which style do you prefer?
    • Let's try the next example of a list of lists - tic-tac-toe board.
      def printBoard(board):
          for r in range(len(board)):
              for c in range(len(board)):
                  print(board[r][c], end='')  # end='' gives no new line
                  if c == 0 or c == 1:
                      print('|', end='')
              print()  # new line
              if r != 2:
                print('-+-+-')
      
      board = [[' ', 'O', ' '], ['X', ' ', 'X'], [' ', ' ', ' ']]  # a tic-tac-toe board
      print(board[0])
      print(board[1])
      print(board[2])
      print(board[0][1])
      printBoard(board)
      
    • Let's try the next example of a list of lists - 3×3 puzzle board.
      def printHorzLine(board):  # n×n board
          for c in range(len(board[0]) * 2 - 1 + 2):
              if c % 2 == 0:
                  print('+', end='')
              else:
                  print('-', end='')
          print()
      
      def printBoard(board):
          printHorzLine(board)
          for r in range(len(board)):
              print('|', end='')
              for c in range(len(board)):
                  print(board[r][c], end='')
                  if c != len(board[r]) - 1:
                      print('|', end='')
              print('|')
              printHorzLine(board)
      
      board = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', ' ']]  # a 3×3-Puzzle board
      printBoard(board)
      
  5. Programming exercises
    1. Write a program that reads multiple student records, saves them in a variable, and prints the average gpa. Each student record should be a dictionary having the keys, 'name', and 'gpa'.
    2. Tic-tac-toe game
      • Data structure for tic-tac-toe board
        • Using a dictionary, ???
        • Using a list, ???
        • Using a list of lists, ???
        • Using a list of lists - For example, [[' ','O',' '],['X','X',' '],[' ',' ',' ']]
            |O|
           -+-+-
           X|X| 
           -+-+-
            | |
           
      • Write a function that receives a tic-tac-toe board and draws the board.
      • Write a program that plays tic-tac-toe. (Hint. The user can enter the board row and column numbers instead of mouse clicking.) (Refer the programming exercises c) in the previous chapter.)
    3. 3×3 puzzle game
      • Data structure for 3×3 board
        • Using a dictionary, ???
        • Using a list, ???
        • Using a list of lists - For example, [[4,8,5],[1,2,0],[3,6,7]]
           +-+-+-+
           |4|8|5|
           +-+-+-+
           |1|2| |
           +-+-+-+
           |3|6|7|
           +-+-+-+
           
        • The empty tile - The integer value, 0, in the board
      • Data structure for a position (or location) of a time
        • A tuple of row and column, where row and column start from 0
        • For example, (1, 2)
      • Write a function that makes a 3×3 board. The board should have randomly scattered numbers from 0 to 8. (Note that 0 will be used as the empty tile in the game.) (Refer the programming exercises d) in the previous chapter.)
      • Write a function that receives a 3×3 board, and prints it. 0 should be printed as a space, i.e., ' '. For example,
         +-+-+-+
         |4|8|5|
         +-+-+-+
         |1|2| |
         +-+-+-+
         |3|6|7|
         +-+-+-+
         
      • Write a function that receives a tuple represening a position of row and column. The function checks if 0 <= row < 3 and 0 <= column < 3, and returns the result.
      • Write a function that receives a 3×3 board, and a tuple of row and column. It checks if (row,column) is a neighbor of the empty tile, and returns the result.
      • Write a function that receives a 3×3 board, and returns a tuple of the position of the empty tile.
      • Write a function that receives a 3×3 board, and two tuples of position0(=(row0,column0)) and position1=((row1,column1)). It swaps the two values in the board, which are pointed by position0 and position1.
      • Write a program that plays the 3×3 puzzle game, using the above functions. (Hint. The user can enter the board row and column numbers instead of mouse clicking.)
        Here is a solution.
  6. References